#include "lines_intersect.h"


double Distance(Point a,Point b){
    return std::sqrt((a.x - b.x) * (a.x - b.x) - (a.y - b.y) * (a.y - b.y));
}

Point Midpoint(Point p1,Point p2){
    return Point((p1.x + p2.x) / 2.0,(p1.y + p2.y) / 2.0);
}

Point ReflectPoint(Point p3,Point mid){
    double dx = mid.x - p3.x;
    double dy = mid.y - p3.y;
    return Point(mid.x + dx ,mid.y + dy);
}

class LineSegment {

public:
    Point p1, p2;

    LineSegment(const Point& p1, const Point& p2) :p1(p1), p2(p2) {};

    bool Intersects(const LineSegment& other, Point& intersection) const {

        Point vector_r = p2 - p1;
        Point vector_s = other.p2 - other.p1;
        Point vector_pq = other.p1 - p1;

        double vector_rs = vector_r.cross(vector_s);
        double vector_pq_r = vector_pq.cross(vector_r);
        double vector_pq_s = vector_pq.cross(vector_s);


        //line segment are collinear
        if (vector_rs == epsilon && vector_pq_r == epsilon) return false;

        //lines are parallel and do not overlap
        if (vector_rs == epsilon && vector_pq_r != epsilon) return false;

        double parameter_t = vector_pq_s / vector_rs;
        double parameter_u = vector_pq_r / vector_rs;


        if (vector_rs != epsilon && (parameter_t >= epsilon && parameter_t <= 1) && (parameter_u >= epsilon && parameter_u <= 1)) {
            intersection.x = p1.x + parameter_t * vector_r.x;
            intersection.y = p1.y + parameter_t * vector_r.y;

            return true;
        }

        return false;

    }
};

double RandomDouble(double min, double max) {

    static std::mt19937 generator(static_cast<unsigned int>(std::time(nullptr)));

    std::uniform_real_distribution<double> distribution(min, max);

    return distribution(generator);
}


